package com.jekunauto.okhttptest;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 查阅过的资料
 * http://www.open-open.com/lib/view/open1484554445349.html
 * http://blog.csdn.net/biezhihua/article/details/50603624
 */
public class MainActivity extends AppCompatActivity {
    private TextView tv_content;
    private TextView tv_content_two;
    private String getSmsUrl = "http://api.jekunauto.com/v2/banners/my-service";

    private String opinionsUrl = "http://api.jekunauto.com/opinions";

    // 电子书下载地址
    private String txtD = "http://down2.txt99.com/d/file/p/txt/2017/%E9%87%8D%E7%94%9F%E6%97%A5%E5%B8%B8.txt";


    //一个缓存目录同时拥有多个缓存访问是错误的。大多数程序只需要调用一次new OkHttp()，在第一次调用时配置好缓存，然后其他地方只需要调用这个实例就可以了.
    // 不建议我们创建多个OkHttpClient，因此全局使用一个。 如果有需要，可以使用clone方法，再进行自定义。这点在后面的高级教程里会提到。
    private OkHttpClient mOkHttpClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content_two = (TextView) findViewById(R.id.tv_content_two);

        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        Cache cache = new Cache(new File("/storage/emulated/0/myokhttpdemo"), cacheSize);
        // step 1: 创建 OkHttpClient 对象
        mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)// 连接超时
                .readTimeout(60, TimeUnit.SECONDS)// 读取超时
                .writeTimeout(60, TimeUnit.SECONDS)// 写入超时
                .cache(cache)// 配置好缓存
                .build();

        // mOkHttpClient.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port)));

        // step 2： 创建一个请求，不指定请求方法时默认是GET。
        final Request request = new Request.Builder().url(getSmsUrl).method("GET", null).build();
        //可以省略，默认是GET请求
        // request.method("GET",null);

        // step 3：创建 Call 对象
        Call call = mOkHttpClient.newCall(request);// 访问

        //step 4: 开始异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //这里是子线程
                Log.e("onFailure-->", e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //这里是子线程,必须使用handler来更新textview的数据显示
                Message message = new Message();
                message.what = 1;
                message.obj = response.body().string();
                handler.sendMessage(message);
            }
        });

        //post请求测试,提交表单键值对
        RequestBody body = new FormBody.Builder()
                .add("user_name", "echo")
                .add("opinion", "okhttp测试")
                .build();
        Request postRequest = new Request.Builder()
                .url(opinionsUrl)
                .post(body).build();

        Call mCall = mOkHttpClient.newCall(postRequest);
        mCall.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

                Log.e("post-failure-->", e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Message message = new Message();
                message.what = 2;
                message.obj = response.body().string();
                handler.sendMessage(message);
            }
        });

    }

    /**
     * 上传文件
     *
     * @param view
     */
    public void upFile(View view) {
        //step 2:创建 RequestBody 以及所需的参数
        //2.1 获取文件
        File file = new File("/storage/emulated/0/test.txt");// SDcard根目录下自己新建个test.txt文件
        //2.2 创建 MediaType 设置上传文件类型
        // text/html	HTML格式
        // text/plain	纯文本格式
        // text/xml	XML格式
        // image/gif	gif图片格式
        // image/jpeg	jpg图片格式
        // image/png	png图片格式
        // application/xhtml+xml	XHTML格式
        // application/xml	XML数据格式
        // application/atom+xml	Atom XML聚合格式
        // application/json	JSON数据格式
        // application/pdf	pdf格式
        // application/msword	Word文档格式
        // application/octet-stream	二进制流数据
        MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8");// 文本类型
        //2.3 获取请求体
        RequestBody requestBody = RequestBody.create(MEDIATYPE, file);

        //step 3：创建请求
        Request requestthree = new Request.Builder().url("http://www.baidu.com")
                .post(requestBody)
                .build();

        //step 4 建立联系
        mOkHttpClient.newCall(requestthree).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("post-onFailure-->", e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Message message = new Message();
                message.what = 3;
                message.obj = response.body().string();
                handler.sendMessage(message);
            }
        });
    }

    /**
     * 下载电子书
     *
     * @param view
     */
    public void dltxt(View view) {
        try {
            run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 多头
     *
     * @param view
     */
    public void tou(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    runTwo();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

    public void runTwo() throws Exception {
        Request request = new Request.Builder()
                .url("https://api.github.com/repos/square/okhttp/issues")
                .header("User-Agent", "OkHttp Headers.java")
                .addHeader("Accept", "application/json; q=0.5")
                .addHeader("Accept", "application/vnd.github.v3+json")
                .build();

        Response response = mOkHttpClient.newCall(request).execute();
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        System.out.println("Server: " + response.header("Server"));
        System.out.println("Date: " + response.header("Date"));
        System.out.println("Vary: " + response.headers("Vary"));
    }


    public void run() throws Exception {
        Request request = new Request.Builder()
                .url(txtD)
                .build();

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                Headers responseHeaders = response.headers();
                for (int i = 0; i < responseHeaders.size(); i++) {
                    System.out.println(responseHeaders.name(i) + " <--->" + responseHeaders.value(i));
                }

                System.out.println(response.body().string());
            }
        });
    }

    /**
     * 看输出结果主要是测试缓存
     *
     * @throws Exception
     */
    public void runthree() throws Exception {
        Request request = new Request.Builder()
                .url("http://publicobject.com/helloworld.txt")
                .build();

        Response response1 = mOkHttpClient.newCall(request).execute();
        if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);

        String response1Body = response1.body().string();
        System.out.println("Response 1 response:          " + response1);
        System.out.println("Response 1 cache response:    " + response1.cacheResponse());
        System.out.println("Response 1 network response:  " + response1.networkResponse());

        Response response2 = mOkHttpClient.newCall(request).execute();
        if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);

        String response2Body = response2.body().string();
        System.out.println("Response 2 response:          " + response2);
        System.out.println("Response 2 cache response:    " + response2.cacheResponse());
        System.out.println("Response 2 network response:  " + response2.networkResponse());

        System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
    }

    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);// 线程池

    /**
     * 取消一个Call
     * 使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应，将会引发IOException。当call没有必要的时候，使用这个api可以节约网络资源。例如当用户离开一个应用时。不管同步还是异步的call都可以取消。
     * 你可以通过tags来同时取消多个请求。当你构建一请求时，使用RequestBuilder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。
     *
     * @throws Exception
     */
    public void runFour() throws Exception {
        Request request = new Request.Builder()
                .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
                .build();

        final long startNanos = System.nanoTime();
        final Call call = mOkHttpClient.newCall(request);

        // Schedule a job to cancel the call in 1 second.
        executor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
                call.cancel();
                System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
            }
        }, 1, TimeUnit.SECONDS);

        try {
            System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
            Response response = call.execute();
            System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
                    (System.nanoTime() - startNanos) / 1e9f, response);
        } catch (IOException e) {
            System.out.printf("%.2f Call failed as expected: %s%n",
                    (System.nanoTime() - startNanos) / 1e9f, e);
        }
    }

    /**
     * 一个请求多个Client配置
     *
     * @throws Exception
     */
    public void runFive() throws Exception {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.
                .build();
        try {
            Response response = client.newBuilder() // Clone to make a customized OkHttp for this request.
                    .readTimeout(500, TimeUnit.MILLISECONDS)
                    .build()
                    .newCall(request)
                    .execute();
            System.out.println("Response 1 succeeded: " + response);
        } catch (IOException e) {
            System.out.println("Response 1 failed: " + e);
        }

        try {
            Response response = client.newBuilder() // Clone to make a customized OkHttp for this request.
                    .readTimeout(3000, TimeUnit.MILLISECONDS)
                    .build()
                    .newCall(request)
                    .execute();
            System.out.println("Response 2 succeeded: " + response);
        } catch (IOException e) {
            System.out.println("Response 2 failed: " + e);
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    String data_one = (String) msg.obj;
                    tv_content.setText("第一条数据==>" + data_one);
                    break;
                case 2:
                    String data_two = (String) msg.obj;
                    tv_content_two.setText("第二条数据==>" + data_two);
                    break;
                case 3:
                    Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };

}
